package mpbft

import (
	"blockchain/public/entity"
	"blockchain/public/function"
	"crypto/sha256"
	"encoding/json"
	"fmt"
	"time"
)

type prepare1Message struct {
	tradeHash [32]byte
	sign string
	nodeSeq int
}

func prepare1(nodeSeq int){
	tradeSets:=getTrades(nodeSeq)
	tradeSets=orderTrades(tradeSets)
	TradeSet[nodeSeq]=tradeSets
	var prepare1 prepare1Message
	data,_:=json.Marshal(tradeSets)
	prepare1.tradeHash=sha256.Sum256(data)
	prepare1.sign=function.SignHash(prepare1.tradeHash,nodeSeq)
	prepare1.nodeSeq=nodeSeq
	var flagPrepared1=make(chan bool,1)
	sendPrepare1ToPri(nodeSeq,&prepare1,flagPrepared1)
	<-flagPrepared1
}

func sendPrepare1ToPri(nodeSeq int,prepare1 *prepare1Message,flagPrepared1 chan bool){
	for i:=range primarysSeq{
		select {
		case chanPriRecPrepare1[primarysSeq[i]]<-*prepare1:
			FlagPrepared1[nodeSeq][i]<-true
			close(FlagPrepared1[nodeSeq][i])
		default:
			FlagPrepared1[nodeSeq][i]<-true
			close(FlagPrepared1[nodeSeq][i])
		}
	}
	flagPrepared1<-true
	close(flagPrepared1)
}

func orderTrades(t [K*TradeSize]entity.Trade)[K*TradeSize]entity.Trade{//得到一个并集有序交易集合
	flag1:=true
	flag2:=true
	if t[TradeSize].Sender==""{
		for i:=1;i<TradeSize;i++{
			if t[i-1].Timestamp.After(t[i].Timestamp){
				flag2=false
				break
			}
		}
	}else {
		flag1=false
	}

	if (!flag1)||(flag1&&!flag2){
		fmt.Println("108108")
		var tradeOrdered [K*TradeSize] bool
		for i:=0;i<K*TradeSize;i++{
			tradeOrdered[i]=false
		}
		var t1[K*TradeSize] entity.Trade
		var tradeInit entity.Trade
		for i:=0;i<K*TradeSize;i++{
			if t[i].Sender!=""{
				for j:=i+1;j<K*TradeSize;j++{
					if t[j]==t[i]{
						t[j]=tradeInit
					}
				}
			}
		}

		for j:=0;j<K*TradeSize;j++{
			min:=time.Now().Add(50*time.Second)
			var minTimeTradeSeq int
			for i:=0;i<K*TradeSize;i++{
				if t[i].Sender!=""{
					if !(tradeOrdered[i]){
						if t[i].Timestamp.Before(min) {
							min = t[i].Timestamp
							minTimeTradeSeq = i
						}
					}
				}else{
					break
				}
			}
			tradeOrdered[j]=true
			t1[j]=t[minTimeTradeSeq]
		}
	}
	return t
}

func getTrades(nodeSeq int) [K*TradeSize]entity.Trade {//获取交易的并集
	var tradesFromePri [K*TradeSize]entity.Trade
	var tradesFromePri1 [K*TradeSize]entity.Trade
	var tradesFromeP [K][TradeSize]entity.Trade
	counter:=0
	countK:=0
	for data:=range chanNodeRecPre_prepare[nodeSeq]{//节点获取自己pre-prepare通道内的数据
		tradeData,_:=json.Marshal(data.tradeSet)
		res:=function.VerifySign(tradeData,data.clientSign,clientSeq)
		res1:=function.VerifySign(tradeData,data.sign,data.priSeq)
		if res&&res1{
			tradesFromeP[countK]=data.tradeSet
			countK++
			for j:=0;j<TradeSize;j++ {
				tradesFromePri[counter]=data.tradeSet[j]
				//fmt.Printf(tradesFromePri[j].sender)
				//fmt.Printf("%d",j)
				//println(counter)
				counter++
			}
		}else {
			fmt.Printf("主节点%d出现拜占庭",data.priSeq)
		}
	}

	for i:=1;i<K;i++{
		if tradesFromeP[i]!=tradesFromeP[0]{
			for i:=0;i<TradeSize;i++{
				tradesFromePri1[i]=tradesFromePri[i]
			}
			count1:=TradeSize
			for i:=TradeSize;i<K*TradeSize;i++{
				flag:=true
				for j:=0;j<TradeSize;j++{
					if tradesFromePri1[j]==tradesFromePri1[i]{
						flag=false
						break
					}
				}
				if flag{
					tradesFromePri1[count1]=tradesFromePri1[i]
					count1++
				}
			}
			fmt.Println("109109")
			return tradesFromePri1
		}
	}
	for i:=0;i<TradeSize;i++{
		tradesFromePri1[i]=tradesFromePri1[i];
	}
	return tradesFromePri1
}